using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using NPOI.SS.Formula.Functions;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SkiaSharp;
using Image = System.Drawing.Image;

namespace Publicuse.Util
{
  /// <summary>
  /// 图片工具类
  /// </summary>
  public class ImageUtil
  {
    /// <summary>
    /// 图片压缩
    /// </summary>
    /// <param name="width"></param>
    /// <param name="imgPath"></param>
    /// <param name="msg"></param>
    public static void CompressImg(int width, string imgPath, out string msg)
    {
      msg = string.Empty;
      try
      {
        using (var imgBmp = new Bitmap(imgPath))
        {
          var oWidth = imgBmp.Width;
          var oHeight = imgBmp.Height;
          var height = oHeight;
          if (width > oWidth)
          {
            width = oWidth;
          }
          else
          {
            height = width * oHeight / oWidth;
          }
          var newImg = new Bitmap(imgBmp, width, height);
          newImg.SetResolution(72, 72);
          var ms = new MemoryStream();
          newImg.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
          var bytes = ms.GetBuffer();
          ms.Close();
        }
      }
      catch (Exception ex)
      {
        msg = ex.Message;
      }
    }

    /// <summary>
    /// 编码
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public static string UrlEncode(string data)
    {
      return HttpUtility.UrlEncode(data, Encoding.UTF8);
    }

    /// <summary>
    /// 解码
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public static string GG(string data)
    {
      return HttpUtility.UrlDecode(data, Encoding.UTF8);
    }

    /// <summary>
    /// 图片压缩
    /// </summary>
    /// <param name="imagePath">图片文件路径</param>
    /// <param name="targetFolder">保存文件夹</param>
    /// <param name="quality">压缩质量</param>
    /// <param name="fileSuffix">压缩后的文件名后缀（防止直接覆盖原文件）</param>
    public static void CompressionImage(
      string imagePath,
      string targetFolder,
      long quality = 100,
      string fileSuffix = "compress"
    )
    {
      if (!File.Exists(imagePath))
      {
        throw new FileNotFoundException();
      }
      if (!Directory.Exists(targetFolder))
      {
        Directory.CreateDirectory(targetFolder);
      }
      var fileInfo = new FileInfo(imagePath);
      var fileName = fileInfo.Name.Replace(fileInfo.Extension, "");
      var fileFullName = Path.Combine(
        $"{targetFolder}",
        $"{fileName}_{fileSuffix}{fileInfo.Extension}"
      );

      var imageByte = CompressionImage(imagePath, quality);
      var ms = new MemoryStream(imageByte);
      var image = Image.FromStream(ms);
      image.Save(fileFullName);
      ms.Close();
      ms.Dispose();
      image.Dispose();
    }

    /// <summary>
    /// 图片压缩
    /// </summary>
    /// <param name="imagePath"></param>
    /// <param name="quality"></param>
    /// <returns></returns>
    public static byte[] CompressionImage(string imagePath, long quality)
    {
      using (var fileStream = new FileStream(imagePath, FileMode.Open))
      {
        using (var img = Image.FromStream(fileStream))
        {
          using (var bitmap = new Bitmap(img))
          {
            var codecInfo = GetEncoder(img.RawFormat);
            var myEncoder = System.Drawing.Imaging.Encoder.Quality;
            var myEncoderParameters = new EncoderParameters(1);
            var myEncoderParameter = new EncoderParameter(myEncoder, quality);
            myEncoderParameters.Param[0] = myEncoderParameter;
            using (var ms = new MemoryStream())
            {
              bitmap.Save(ms, codecInfo, myEncoderParameters);
              myEncoderParameters.Dispose();
              myEncoderParameter.Dispose();
              return ms.ToArray();
            }
          }
        }
      }
    }

    private static ImageCodecInfo GetEncoder(ImageFormat format)
    {
      var codecs = ImageCodecInfo.GetImageDecoders();
      return codecs.FirstOrDefault(codec => codec.FormatID == format.Guid);
    }

    /// <summary>
    /// 压缩图片 SkiaSharp
    /// </summary>
    /// <param name="source">原文件位置</param>
    /// <param name="target">生成目标文件位置</param>
    /// <param name="maxWidth">最大宽度，根据此宽度计算是否需要缩放，计算新高度</param>
    /// <param name="quality">图片质量，范围0-100</param>
    public static void Compress(string source, string target, decimal maxWidth, int quality)
    {
      using (var file = File.OpenRead(source))
      using (var fileStream = new SKManagedStream(file))
      using (var bitmap = SKBitmap.Decode(fileStream))
      {
        var width = (decimal)bitmap.Width;
        var height = (decimal)bitmap.Height;
        var newWidth = width;
        var newHeight = height;
        if (width > maxWidth)
        {
          newWidth = maxWidth;
          newHeight = height / width * maxWidth;
        }
        using (
          var resized = bitmap.Resize(
            new SKImageInfo((int)newWidth, (int)newHeight),
            SKFilterQuality.Medium
          )
        )
        {
          if (resized != null)
          {
            using (var image = SKImage.FromBitmap(resized))
            using (var writeStream = File.OpenWrite(target))
            {
              image.Encode(SKEncodedImageFormat.Jpeg, quality).SaveTo(writeStream);
            }
          }
        }
      }
    }

    /// <summary>
    /// 压缩图片 SixLabors.ImageSharp
    /// 如果设置了宽或者高，然后另一个参数设置为 0 ，那么 ImageSharp 将会保持图片纵横比来进行调整大小。
    ///还有更多的设置，比如设置图片质量等，请参阅官方文档：https://docs.sixlabors.com/articles/imagesharp/resize.html
    ///使用此组件，可任意跨平台，无需安装外部依赖
    /// </summary>
    /// <param name="source">原文件位置</param>
    /// <param name="target">生成目标文件位置</param>
    public static void Compressexport(string source, string target)
    {
      using (SixLabors.ImageSharp.Image image = SixLabors.ImageSharp.Image.Load(source))
      {
        image.Mutate(x => x.Resize(400, 400));
        image.Save(target);
      }
    }

    /// <summary>
    /// 压缩图片 NetVips
    /// 此组件是基于 C 的库 libvips 来封装的，性能高，资源占用低。并且经过完全测试，跨平台且没有内存泄漏。
    /// </summary>
    /// <param name="source">原文件位置</param>
    /// <param name="target">生成目标文件位置</param>
    public static void Compressexportb(string source, string target)
    {
      using (var image = NetVips.Image.NewFromFile(source))
      {
        var newImg = image.ThumbnailImage(400, 400);
        newImg.WriteToFile(target);
      }
    }

    /// <summary>
    /// 压缩图片 SixLabors.ImageSharp
    /// </summary>
    /// <param name="source">原文件位置</param>
    /// <param name="target">生成目标文件位置</param>
    public static void Compressc(string source, string target)
    {
      using (SixLabors.ImageSharp.Image image = SixLabors.ImageSharp.Image.Load(source))
      {
        image.Mutate(x => x.Resize(500, 500));
        image.Save(target);
      }
    }

    /// <summary>
    /// 判断当前文件是否图片
    /// </summary>
    /// <param name="filePath"></param>
    /// <returns></returns>
    public static bool IsImage(string filePath)
    {
      string extension = Path.GetExtension(filePath);
      string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif", ".bmp" }; // 可根据需要添加其他图片格式的扩展名
      return imageExtensions.Contains(extension.ToLower());
    }

    /// <summary>
    /// 判断是否为图片文件
    /// </summary>
    /// <param name="filePath"></param>
    /// <returns></returns>
    public static bool IsImageByImageSharp(string filePath)
    {
      try
      {
        // 使用 Image.Load 检测文件是否为有效图片
        using (var image = SixLabors.ImageSharp.Image.Load(filePath))
        {
          return true;
        }
      }
      catch (SixLabors.ImageSharp.UnknownImageFormatException)
      {
        // 格式不支持或不是图片
        return false;
      }
      catch (Exception)
      {
        // 其他异常，如文件不存在等
        return false;
      }
    }
  }
}
